class MedianFinder {
    PriorityQueue<Integer> lowers;
    PriorityQueue<Integer> highers;
    double median;

    public MedianFinder() {
        lowers = new PriorityQueue<>(Collections.reverseOrder());
        highers = new PriorityQueue<>();
        median = 0;
    }
    
    public void addNum(int num) {
        if(lowers.isEmpty() || num < lowers.peek()) {
            lowers.add(num);
        } else {
            highers.add(num);
        }

        rebalancePQs();
        updateMedian();
    }

    private void rebalancePQs() {
        if(lowers.size() - highers.size() == 2) {
            highers.add(lowers.remove());
        } else if(highers.size() - lowers.size() == 2) {
            lowers.add(highers.remove());
        }
    }

    private void updateMedian() {
        if(lowers.size() > highers.size()) {
            median = lowers.peek();
        } else if(highers.size() > lowers.size()) {
            median = highers.peek();
        } else {
            median = (lowers.peek() + highers.peek()) / 2.0;
        }
    }
    
    public double findMedian() {
        return median;
        
    }
}

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */